﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "CreateStructureInstanceCmd.h"
#include "GmUiStructureCommandRegister.h"
#include "DebugMessage.h"
#include "CommandParameters.h"
#include "IDocument.h"
#include "IFamily.h"
#include "IElementBasicInformation.h"
#include "InstancePlacementTypes.h"
#include "StructureInstanceCmdUtils.h"
#include "StructureCmdParamIds.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include "StructureInstanceSecondKeys.h"
#include "ICommandManager.h"
#include "StructureCmdIds.h"
#include "CmdStatusUtils.h"
#include "UiDocumentViewUtils.h"
#include "GcmpCommandNames.h"
#include "GbmpUiPlatformCommandIds.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

REGISTER_GM_COMMAND(CreateStructureInstanceCmd)

CreateStructureInstanceCmd::CreateStructureInstanceCmd()
    : GbmpCommandBase(ID_CMD_GBMP_CREATE_FAMILY_INSTANCE)
{
}

CreateStructureInstanceCmd::~CreateStructureInstanceCmd()
{
}

OwnerPtr<IAction> CreateStructureInstanceCmd::ExecuteCommand(const CommandParameters& cmdParams)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(cmdParams.size() == 2, L"CreateStructureInstanceCmd命令参数个数不正确",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    // 获取familyName
    auto itor = cmdParams.find(ID_CMD_PARAM_FAMILY_NAME);   // L"FamilyName"
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(itor != cmdParams.end(), L"所需的参数不存在",L"GDMPLab",L"2024-03-30");
    std::wstring familyName = itor->second.AsWString();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!familyName.empty(), L"familyName为空",L"GDMPLab",L"2024-03-30");

    // 获取familyTypeName
    itor = cmdParams.find(L"FamilyType");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(itor != cmdParams.end(), L"所需的参数不存在",L"GDMPLab",L"2024-03-30");
    std::wstring familyTypeName = itor->second.AsWString();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!familyTypeName.empty(), L"familyTypeName为空",L"GDMPLab",L"2024-03-30");

    // 获取 pFamily 和 pFamilyType
    IFamily* pFamily = IFamily::GetFamilyByName(pDoc, familyName);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamily, L"pFamily为空",L"GDMPLab",L"2024-03-30");
    const IFamilyType* pFamilyType = ((const IFamily*)pFamily)->GetFamilyTypeByName(familyTypeName);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamilyType, L"pFamilyType为空",L"GDMPLab",L"2024-03-30");

    // 获取放置类型
    InstancePlacementTypes posType = InstancePlacementTypes::Invalid;
    bool isOk = StructureInstanceCmdUtils::GetInstancePlacementType(pFamilyType, posType);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(isOk, L"获取放置类型失败",L"GDMPLab",L"2024-03-30");

    // 获取familyCategoryUid
    const UniIdentity& familyCategoryUid = pFamily->GetBasicInformation()->GetCategoryUid();

    // 记录当前的familyName和instanceType
    CommandParameters cmdParameters;
    cmdParameters[ID_CMD_PARAM_FAMILY_NAME] = familyName;
    cmdParameters[ID_CMD_PARAM_INSTANCE_TYPE] = familyTypeName;

    ICommandManager *pCmdMgr = ICommandManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCmdMgr, L"invalid pCmdMgr",L"GDMPLab",L"2024-03-30");

    // 根据放置类型启动不同的cmd
    switch (posType)
    {
    case InstancePlacementTypes::OnWorkPlane:   // 点式族、线式族的放置方式
    {
        if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_POINT_FAMILY
            || familyCategoryUid == BuiltInCategoryUniIdentities::BICU_IMPORTED_SKP_OBJECT)
        {
            pCmdMgr->SendCommand(ID_CMD_CREATE_GBMP_POINT_FAMILY_INSTANCE, cmdParameters);
        }
        else if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_LINE_FAMILY)
        {
            pCmdMgr->SendCommand(ID_CMD_CREATE_GBMP_LINE_FAMILY_INSTANCE, cmdParameters);
        }
        else if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_NEW_ROOF)
        {
            pCmdMgr->SendCommand(ID_CMD_CREATE_STRUCTURE_ROOF, cmdParameters);
        }
        else
        {
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"暂时不支持此种类别的族实例化",L"GDMPLab",L"2024-03-30");
        }
    }
    break;

    case InstancePlacementTypes::OnHost:   // 墙洞的放置方式
    {
        if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_STRUCTURE_WALL_HOLE)
        {
            pCmdMgr->SendCommand(ID_CMD_DRAW_RECT_STRUCTURE_WALL_HOLE, cmdParameters);
        }
        else if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_WINDOW)
        {
            pCmdMgr->SendCommand(ID_CMD_FAMILY_DRAW_WINDOW, cmdParameters);
        }
        else
        {
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"暂时不支持此种类别的族实例化",L"GDMPLab",L"2024-03-30");
        }
    }
    break;

    case InstancePlacementTypes::MutiPoints:   // 栏杆扶手的放置方式
    {

    }
    break;

    case InstancePlacementTypes::OnLevel:   // 结构墙、结构梁、结构柱的放置方式
    {
        // 获取子类别
        int categorySubType;
        bool isOK = StructureInstanceCmdUtils::GetCategorySubType(pFamilyType, categorySubType);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(isOk, L"获取子类别失败",L"GDMPLab",L"2024-03-30");

        if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_STRUCTURE_WALL)
        {
            if (categorySubType == (int)StructureWallType::Basic)
            {
                pCmdMgr->SendCommand(ID_CMD_DRAW_STRUCTURE_STRAIGHT_WALL, cmdParameters);
            }
            else if (categorySubType == (int)StructureWallType::VariableSection)
            {
                pCmdMgr->SendCommand(ID_CMD_DRAW_VARIABLE_SECTION_STRUCTURE_STRAIGHT_WALL, cmdParameters);
            }
        }
        else if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_STRUCTURE_BEAM)
        {
            if (categorySubType == (int)StructureBeamType::Basic)
            {
                pCmdMgr->SendCommand(ID_CMD_CREATE_STRAIGHT_STRUCTURE_BEAM, cmdParameters);
            }
            else if (categorySubType == (int)StructureBeamType::VariableSection)
            {
                pCmdMgr->SendCommand(ID_CMD_CREATE_STRAIGHT_STRUCTURE_VARIABLE_SECTION_BEAM, cmdParameters);
            }
            else if (categorySubType == (int)StructureBeamType::CustomizedProfile)
            {
                pCmdMgr->SendCommand(ID_CMD_CREATE_STRAIGHT_STRUCTURE_CUSTOMIZED_PROFILE_BEAM, cmdParameters);
            }
        }
        else if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_STRUCTURE_COLUMN)
        {
            pCmdMgr->SendCommand(ID_CMD_DRAW_STRUCTURE_VERTICAL_COLUMN, cmdParameters);
        }
        else if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_LINE_FAMILY)
        {
            pCmdMgr->SendCommand(ID_CMD_CREATE_LINEAR_INSTANCE, cmdParameters);
        }
        else
        {
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"暂时不支持此种类别的族实例化",L"GDMPLab",L"2024-03-30");
        }
    }
    break;

    case InstancePlacementTypes::FamilyBasedOnProfile:   // 楼板、筏板基础、板洞的放置方式
    {
        if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_STRUCTURE_FLOOR)
        {
            pCmdMgr->SendCommand(ID_CMD_CREATE_STRUCTURE_FLOOR, cmdParameters);
        }
        else if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_STRUCTURE_FOUNDATION)
        {
            pCmdMgr->SendCommand(ID_CMD_CREATE_RAFT_FOUNDATION, cmdParameters);
        }
        else if (familyCategoryUid == BuiltInCategoryUniIdentities::BICU_STRUCTURE_PLATE_HOLE)
        {
            pCmdMgr->SendCommand(ID_CMD_CREATE_STRUCTURE_PLATE_HOLE, cmdParameters);
        }
        else
        {
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"暂时不支持此种类别的族实例化",L"GDMPLab",L"2024-03-30");
        }
    }
    break;

    default:
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"暂时不支持此种类别的族实例化",L"GDMPLab",L"2024-03-30");
    }
    break;
    }

    return nullptr;
}

bool CreateStructureInstanceCmd::IsEnabled() const
{
    CMD_ONLY_ENABLE_IN_PROJECT_ENVIRONMENT
}
bool CreateStructureInstanceCmd::IsVisible() const
{
    CMD_ONLY_VISIBLE_IN_PROJECT_ENVIRONMENT
}
